/**
 * 染膏机蓝牙B协议，4g + 蓝牙通道
 * 66+00(备用)+0000(命令2字节)+MAC(6字节)+系统时间(6字节)+副机号(2字节)+副机总数(2字节)+行号(2字节)+状态标志(2字节)+参数长度(2字节)+参数+累加取反(1字节)
 */
const verify = (upData) => {
  if (upData == null || upData == '') {
    return ResponseVo.error('数据为空')
  }
  upData = upData.toUpperCase()

  if (!upData.startsWith('66')) {
    return ResponseVo.error('非法数据，启始位非66')
  }

  let dataLength = upData.length
  if (dataLength % 2 != 0) {
    return ResponseVo.error('HEX字符数必须为偶数')
  }

  let byteNum = dataLength / 2

  let hexLength = takeHex(upData, 24, 2)
  let length = hexToInt(hexLength)
  // if ((27 + length) != byteNum) {
  // 	return ResponseVo.error("长度" + hexLength + "不正确 upData=" + upData);
  // }

  let mac = takeHex(upData, 4, 6)
  let command = takeHex(upData, 2, 2)
  let hexSysTime = takeHex(upData, 10, 6)
  let hexSubSn = takeHex(upData, 16, 2)
  let hexSubTotal = takeHex(upData, 18, 2)
  let hexRow = takeHex(upData, 20, 2)
  let hexStatusNo = takeHex(upData, 22, 2)
  let hexParamLength = takeHex(upData, 24, 2)
  let paramLength = hexToInt(hexParamLength)
  let hexParam = takeHex(upData, 26, paramLength) //内容
  let agree = new AgreeBInfo(mac, command, hexSysTime, hexSubTotal, hexRow, hexStatusNo, hexParamLength, hexParam)
  return ResponseVo.success(agree)
}
const down = (mac, command, param, sysTime, paramCheckType) => {
  return downData(mac, command, sysTime, 0, 0, 0, '', param, paramCheckType)
}
/**
 * @param {Object} mac
 * @param {Object} command
 * @param {Object} sysTime
 * @param {Object} subSn
 * @param {Object} subTotal
 * @param {Object} rowIdx
 * @param {Object} statusNo
 * @param {Object} param
 * @param {Object} paramCheckType 参数校验类型 crc, md5
 */
const downData = (mac, command, sysTime, subSn, subTotal, rowIdx, statusNo, param, paramCheckType) => {
  mac = mac == (null || undefined) ? '' : mac
  mac = mac.padStart(12, '0')
  command = command == (null || undefined) ? '' : command
  command = command.padStart(4, '0')
  sysTime = sysTime == (null || undefined || '') ? dateFormat(new Date()) : sysTime
  sysTime = sysTime.padStart(12, '0')
  subSn = subSn == (null || undefined) || subSn < 0 ? 0 : subSn
  subTotal = subTotal == (null || undefined) || subTotal < 0 ? 0 : subTotal
  rowIdx = rowIdx == (null || undefined) || rowIdx < 0 ? 0 : rowIdx
  param = param == (null || undefined) ? '' : param
  statusNo = statusNo == (null || undefined || '') ? '' : statusNo
  statusNo = statusNo.padStart(4, '0')
  let hexSubSn = intToHex(subSn)
  hexSubSn = hexSubSn.padStart(4, '0')
  let hexSubTotal = intToHex(subTotal)
  hexSubTotal = hexSubTotal.padStart(4, '0')
  let hexRowIdx = intToHex(rowIdx)
  hexRowIdx = hexRowIdx.padStart(4, '0')
  let paramLength = param.length / 2 + 2 //加上crc校验2字节
  let hexParamLength = intToHex(paramLength)
  hexParamLength = hexParamLength.padStart(4, '0')
  //01100033000306000103E9001E 7A08
  //let crc = MODBUS_CRC(new Buffer("01100033000306000103E9001E", "hex"));
  let hexParamCheck = ''
  let hexParams = Str2Bytes(param)
  console.log('params123123', param)
  if (paramCheckType != undefined && paramCheckType.toUpperCase() == 'CRC') {
    hexParamCheck = MODBUS_CRC(hexParams)
  }
  console.log("hexParamCheck: ", hexParamCheck);
  let data = '6600' + command + mac + sysTime + hexSubSn + hexSubTotal + hexRowIdx + statusNo + hexParamLength + param + hexParamCheck
  let check = checksumReverse(data)
  data += check

  return data
}

function AgreeBInfo (mac, command, hexSysTime, hexSubTotal, hexRow, hexStatusNo, hexParamLength, hexParam) {
  this.mac = mac
  this.command = command
  this.hexSysTime = hexSysTime
  this.hexSubTotal = hexSubTotal
  this.hexRow = hexRow
  this.hexStatusNo = hexStatusNo
  this.hexParamLength = hexParamLength
  this.hexParam = hexParam
}

const intToHex = (val) => {
  let hex = val.toString(16)
  return hex
}
const hexToInt = (hex) => {
  let val = parseInt(hex, 16)
  return val
}

var padLeft = function(ret, padChar, len) {
	if (padChar == undefined || padChar == null) {
		padChar = "";
	}
	while (ret.length < len) {
		if (ret.length + padChar.length < len) {
			ret = padChar + ret;
		} else {
			ret = padChar.substring(0, len - ret.length) + ret;
		}

	}
	return ret;
};

const takeHex = (hex, off, length) => {
  console.log(hex, off, length,111)
  try {
    if (hex == null || hex.length % 2 != 0) {
      return ''
    }
    if (off * 2 + length * 2 > hex.length) {
      return ''
    }
    let beginIndex = off * 2
    let endIndex = beginIndex + length * 2
    return hex.substring(beginIndex, endIndex)
  } catch (e) {}
  return ''
}

class ResponseVo {
  constructor(code, message, data) {
    this.code = code
    this.message = message
    this.data = data
  }
  static success(data) {
    this.code = 0
    this.message = ''
    this.data = data
    return new ResponseVo(this.code, this.message, this.data)
  }
  static error(message) {
    this.code = 1
    this.message = message
    this.data = null
    return new ResponseVo(this.code, this.message, this.data)
  }
}
const dateFormat = (d) => {
  let curr_date = d.getDate()
  let curr_month = d.getMonth() + 1
  let curr_year = d.getFullYear()
  let curr_hour = d.getHours()
  let curr_minutes = d.getMinutes()
  let curr_seconds = d.getSeconds()

  String(curr_month).length < 2 ? (curr_month = '0' + curr_month) : curr_month
  String(curr_date).length < 2 ? (curr_date = '0' + curr_date) : curr_date
  String(curr_hour).length < 2 ? (curr_hour = '0' + curr_hour) : curr_hour
  String(curr_minutes).length < 2 ? (curr_minutes = '0' + curr_minutes) : curr_minutes
  String(curr_seconds).length < 2 ? (curr_seconds = '0' + curr_seconds) : curr_seconds

  let yearStr = String(curr_year)
  yearStr = yearStr.substring(2)
  let yyMMddHHmmss = yearStr + '' + curr_month + '' + curr_date + curr_hour + curr_minutes + curr_seconds
  return yyMMddHHmmss
}

/**
 * 十进制转十六进制
 * @param {Object} value 十进制值
 */
const memoryHex = (value) => {
  return (value >= 0 ? value : 0x100000000 + value).toString(16)
}
/**
 * @param {Object} data 累加求和取反取低字节
 */
const checksumReverse = (data) => {
  if (data == null || data == '') {
    return ''
  }
  if (data.length % 2 != 0) {
    return ''
  }
  let total = 0
  let len = data.length
  let num = 0
  while (num < len) {
    let s = data.substring(num, num + 2)
    total += hexToInt(s)
    num = num + 2
  }
  //let mod = total % 256;
  let reverseVal = ~total
  let hex = memoryHex(reverseVal)
  let hexLen = hex.length
  if (hexLen < 2) {
    hex = '0' + hex
  } else {
    hex = hex.substr(hexLen - 2, 2)
  }
  return hex
}

//十六进制字符串转字节数组
function Str2Bytes(str) {
  var pos = 0;
  var len = str.length;
  if (len % 2 != 0) {
    return null;
  }
  len /= 2;
  var hexA = new Array();
  for (var i = 0; i < len; i++) {
    var s = str.substr(pos, 2);
    var v = parseInt(s, 16);
    hexA.push(v);
    pos += 2;
  }
  return hexA;
}

/**
 *  MODBUS-RTU CRC校验
 * @param data Buffer对象十六进制Hex
 * @returns {any[]}  十六进制高低位
 */
const MODBUS_CRC = (data) => {
  let crcValue = 0xffff
  for (let i = 0; i < data.length; i++) {
    crcValue ^= data[i] & 0xffff
    for (let j = 0; j < 8; j++) {
      if (crcValue & 0x0001) {
        crcValue >>= 1
        crcValue ^= 0xa001
      } else {
        crcValue >>= 1
      }
    }
  }
  crcValue = crcValue.toString(16)
  crcValue = crcValue.padStart(4, '0')
  let crcArr = new Array(2)
  crcArr[0] = crcValue.substring(2, 4)
  crcArr[1] = crcValue.substring(0, 2)
  return crcArr.join('')
}

export default {
  verify,
  down,
  downData,
  intToHex,
  hexToInt,
  takeHex,
  checksumReverse,
  padLeft
}